﻿namespace HutongGames.PlayMakerEditor
{
    using HutongGames.PlayMaker;
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Runtime.CompilerServices;

    public class FsmInfo
    {
        [CompilerGenerated]
        private FsmStateAction action__BackingField;
        [CompilerGenerated]
        private string eventName__BackingField;
        [CompilerGenerated]
        private FieldInfo field__BackingField;
        [CompilerGenerated]
        private Fsm fsm__BackingField;
        [CompilerGenerated]
        private PlayMakerFSM fsmComponent__BackingField;
        [CompilerGenerated]
        private FsmState state__BackingField;
        [CompilerGenerated]
        private FsmTransition transition__BackingField;
        [CompilerGenerated]
        private NamedVariable variable__BackingField;
        private static FsmInfo currentInfo;

        public FsmInfo()
        {
        }

        public FsmInfo(FsmInfo source)
        {
            this.fsmComponent = source.fsmComponent;
            this.fsm = source.fsm;
            this.state = source.state;
            this.transition = source.transition;
            this.action = source.action;
            this.variable = source.variable;
        }

        public static List<FsmInfo> FindActionsUsingEvent(string eventName)
        {
            return FindActionsUsingEvent(FsmEditor.FsmList, eventName);
        }

        public static List<FsmInfo> FindActionsUsingEvent(Fsm fsm, string eventName)
        {
            List<FsmInfo> list = new List<FsmInfo>();
            foreach (FsmState state in fsm.States)
            {
                foreach (FsmStateAction action in state.Actions)
                {
                    FsmInfo info = new FsmInfo();
                    info.fsm = fsm;
                    info.state = state;
                    info.action = action;
                    currentInfo = info;
                    list.AddRange(FindEventUsage(action, eventName));
                }
            }
            return list;
        }

        public static List<FsmInfo> FindActionsUsingEvent(List<Fsm> fsmSelection, string eventName)
        {
            List<FsmInfo> list = new List<FsmInfo>();
            foreach (Fsm fsm in fsmSelection)
            {
                list.AddRange(FindActionsUsingEvent(fsm, eventName));
            }
            return list;
        }

        private static IEnumerable<FsmInfo> FindEventUsage(object obj, string eventName)
        {
            List<FsmInfo> list = new List<FsmInfo>();
            if (obj != null)
            {
                foreach (FieldInfo info in obj.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance))
                {
                    Type fieldType = info.FieldType;
                    object fieldValue = info.GetValue(obj);
                    if (IsEventUsedInField(fieldType, fieldValue, eventName))
                    {
                        FsmInfo item = new FsmInfo(currentInfo);
                        item.field = info;
                        list.Add(item);
                    }
                    else if (fieldType.IsClass)
                    {
                        list.AddRange(FindEventUsage(fieldValue, eventName));
                    }
                }
            }
            return list;
        }

        public static List<FsmInfo> FindGlobalVariablesUsage(Fsm fsm)
        {
            List<FsmInfo> list = new List<FsmInfo>();
            if ((FsmVariables.GlobalVariables != null) && (fsm != null))
            {
                List<FsmVariable> fsmVariableList = FsmVariable.GetFsmVariableList(FsmVariables.GlobalVariables, null);
                foreach (FsmState state in fsm.States)
                {
                    foreach (FsmStateAction action in state.Actions)
                    {
                        foreach (FsmVariable variable in fsmVariableList)
                        {
                            FsmInfo info = new FsmInfo();
                            info.fsm = fsm;
                            info.state = state;
                            info.action = action;
                            info.variable = variable.NamedVar;
                            currentInfo = info;
                            list.AddRange(FindVariableUsage(action, variable.NamedVar));
                        }
                    }
                }
            }
            return list;
        }

        public static List<FsmState> FindStatesUsingEvent(Fsm fsm, string eventName)
        {
            List<FsmInfo> fsmInfoList = new List<FsmInfo>();
            fsmInfoList.AddRange(FindTransitionsUsingEvent(fsm, eventName));
            fsmInfoList.AddRange(FindActionsUsingEvent(fsm, eventName));
            return GetStateList(fsmInfoList);
        }

        public static List<FsmInfo> FindTransitionsUsingEvent(string eventName)
        {
            return FindTransitionsUsingEvent(FsmEditor.FsmList, eventName);
        }

        public static List<FsmInfo> FindTransitionsUsingEvent(List<Fsm> fsmSelection, string eventName)
        {
            List<FsmInfo> list = new List<FsmInfo>();
            foreach (Fsm fsm in fsmSelection)
            {
                list.AddRange(FindTransitionsUsingEvent(fsm, eventName));
            }
            return list;
        }

        public static List<FsmInfo> FindTransitionsUsingEvent(Fsm fsm, string eventName)
        {
            List<FsmInfo> list = new List<FsmInfo>();
            foreach (FsmState state in fsm.States)
            {
                foreach (FsmTransition transition in state.Transitions)
                {
                    if (transition.EventName == eventName)
                    {
                        FsmInfo item = new FsmInfo();
                        item.fsm = fsm;
                        item.state = state;
                        item.transition = transition;
                        list.Add(item);
                    }
                }
            }
            foreach (FsmTransition transition2 in fsm.GlobalTransitions)
            {
                if (transition2.EventName == eventName)
                {
                    FsmInfo info2 = new FsmInfo();
                    info2.fsm = fsm;
                    info2.state = fsm.GetState(transition2.ToState);
                    info2.transition = transition2;
                    list.Add(info2);
                }
            }
            return list;
        }

        public static List<FsmInfo> FindVariableUsage(NamedVariable findVariable)
        {
            return FindVariableUsage(FsmEditor.FsmList, findVariable);
        }

        public static List<FsmInfo> FindVariableUsage(List<Fsm> fsmSelection, NamedVariable findVariable)
        {
            List<FsmInfo> list = new List<FsmInfo>();
            foreach (Fsm fsm in fsmSelection)
            {
                foreach (FsmState state in fsm.States)
                {
                    foreach (FsmStateAction action in state.Actions)
                    {
                        FsmInfo info = new FsmInfo();
                        info.fsm = fsm;
                        info.state = state;
                        info.action = action;
                        currentInfo = info;
                        list.AddRange(FindVariableUsage(action, findVariable));
                    }
                }
            }
            return list;
        }

        private static IEnumerable<FsmInfo> FindVariableUsage(object obj, NamedVariable findVariable)
        {
            List<FsmInfo> list = new List<FsmInfo>();
            if (obj != null)
            {
                foreach (FieldInfo info in obj.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance))
                {
                    Type fieldType = info.FieldType;
                    object obj2 = info.GetValue(obj);
                    if (fieldType.IsClass)
                    {
                        list.AddRange(FindVariableUsage(obj2, findVariable));
                    }
                    if (IsVariableUsedInField(fieldType, obj2, findVariable))
                    {
                        FsmInfo item = new FsmInfo(currentInfo);
                        item.field = info;
                        list.Add(item);
                    }
                }
            }
            return list;
        }

        public static List<Fsm> GetFsmList(List<FsmInfo> fsmInfoList)
        {
            List<Fsm> list = new List<Fsm>();
            foreach (FsmInfo info in fsmInfoList)
            {
                if ((info.fsm != null) && !list.Contains(info.fsm))
                {
                    list.Add(info.fsm);
                }
            }
            return list;
        }

        public static List<FsmState> GetStateList(List<FsmInfo> fsmInfoList)
        {
            List<FsmState> list = new List<FsmState>();
            foreach (FsmInfo info in fsmInfoList)
            {
                if ((info.state != null) && !list.Contains(info.state))
                {
                    list.Add(info.state);
                }
            }
            return list;
        }

        public static List<NamedVariable> GetVariableList(List<FsmInfo> fsmInfoList)
        {
            List<NamedVariable> list = new List<NamedVariable>();
            foreach (FsmInfo info in fsmInfoList)
            {
                if ((info.variable != null) && !list.Contains(info.variable))
                {
                    list.Add(info.variable);
                }
            }
            return list;
        }

        private static bool IsEventUsedInField(Type fieldType, object fieldValue, string eventName)
        {
            if (fieldValue != null)
            {
                if (fieldType == typeof(FsmEvent))
                {
                    FsmEvent event2 = (FsmEvent) fieldValue;
                    return (eventName == event2.Name);
                }
                if (fieldType.IsArray)
                {
                    Array array = (Array) fieldValue;
                    Type elementType = fieldType.GetElementType();
                    if (elementType == typeof(FsmEvent))
                    {
                        for (int i = 0; i < array.Length; i++)
                        {
                            if (IsEventUsedInField(elementType, array.GetValue(i), eventName))
                            {
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        }

        private static bool IsVariableUsedInField(Type fieldType, object fieldValue, NamedVariable findVariable)
        {
            if (fieldValue != null)
            {
                if (fieldType.IsSubclassOf(typeof(NamedVariable)))
                {
                    NamedVariable variable = (NamedVariable) fieldValue;
                    return (variable == findVariable);
                }
                if (fieldType == typeof(FsmOwnerDefault))
                {
                    FsmOwnerDefault default2 = (FsmOwnerDefault) fieldValue;
                    if ((default2.OwnerOption == OwnerDefaultOption.SpecifyGameObject) && (default2.GameObject == findVariable))
                    {
                        return true;
                    }
                }
                if (fieldType.IsArray)
                {
                    Array array = (Array) fieldValue;
                    Type elementType = fieldType.GetElementType();
                    for (int i = 0; i < array.Length; i++)
                    {
                        if (IsVariableUsedInField(elementType, array.GetValue(i), findVariable))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        public FsmStateAction action
        {
            [CompilerGenerated]
            get
            {
                return this.action__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.action__BackingField = value;
            }
        }

        public string eventName
        {
            [CompilerGenerated]
            get
            {
                return this.eventName__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.eventName__BackingField = value;
            }
        }

        public FieldInfo field
        {
            [CompilerGenerated]
            get
            {
                return this.field__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.field__BackingField = value;
            }
        }

        public Fsm fsm
        {
            [CompilerGenerated]
            get
            {
                return this.fsm__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.fsm__BackingField = value;
            }
        }

        public PlayMakerFSM fsmComponent
        {
            [CompilerGenerated]
            get
            {
                return this.fsmComponent__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.fsmComponent__BackingField = value;
            }
        }

        public FsmState state
        {
            [CompilerGenerated]
            get
            {
                return this.state__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.state__BackingField = value;
            }
        }

        public FsmTransition transition
        {
            [CompilerGenerated]
            get
            {
                return this.transition__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.transition__BackingField = value;
            }
        }

        public NamedVariable variable
        {
            [CompilerGenerated]
            get
            {
                return this.variable__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.variable__BackingField = value;
            }
        }
    }
}

